#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "tftpser.h"
#define NOTFILESYSTEM
//#define DM642
#define LINUX

#ifndef	NOTFILESYSTEM
	#include <stdio.h>
#endif
#ifdef LINUX
	#include <sys/time.h>
	#include <sys/socket.h>
	#include <sys/select.h>
	#include <unistd.h>
	#include <sys/ioctl.h>
    #include <arpa/inet.h>
	#include <netinet/in.h>
	#include <fcntl.h>

#endif
#ifdef WIN32
	#include <winsock2.h>
	#include <sys/timeb.h>
#endif
#ifdef DM642
	#include <std.h>
	#include <log.h>
	#include <sys.h>
	#include <mem.h>
	#include <sio.h>
	#include <csl.h>
	#include <csl_cache.h>
	#include <netmain.h>
	#include <scom.h>
	#include <socket.h>
	#include <string.h>
	#include <time.h>
#endif

#ifdef	NOTFILESYSTEM
	#define FILE unsigned short
 	#define NFS_SEEK_SET 0
#endif

typedef struct {
	int16  socketfd;		//SOCKET端口句柄
	FILE   *fd;				//文件句柄
	int8   fileName[128];	//文件名
	int32  packNo;			//回应的包号
	int8   sendBuf[BLKSIZE];//发送缓冲区
	uint32 sendBufLen;		//发送缓冲区长度
	uint32 recvBufLen;		//接收数据长度
	uint8  count;			//重发次数
	uint8  stat;			//0 没有收到也没有发出新文件，1 收到新文件，
							//2 发出新文件，3 正在下载文件
	int8   reSendData;		//用于表示需要重发的是什么数据，0-非表示（应答等），1-数据
	int32  fileCurrentDown;	//下载当前文件位置
	int32  fileCurrentSend;	//上传当前文件位置
	int32  resPackNo;		//等待回应的包号，原来的packNo为发送的包号,现在没用
	int32  dataAvailable;	//是否还有数据发送，如果等于0表示数据已经发送完
#ifndef WIN32
	struct timeval tv;
#else
	struct _timeb tstruct;
#endif
	struct sockaddr_in from_addr;
} tftpcon;




#define SENDWINDOW   3              //发送窗口大小
tftpcon m_tftp[MAXCONNNUM];			//结构数组成
TftpFile *m_listFile[MAXLISTFILE];	//文件数组

int16 m_listNum = 0;
uint16 m_blksize = 512;
int16 m_wrqBlkSize = 512;
uint8 g_Ip[4];
uint8 g_Mask[4];
uint8 g_GateWay[4];
uint8 g_MacAddr[6];
uint8 g_bk6 = 0x00;
uint8 g_RunStat;		//有无jpg文件请求标识



struct timeval m_SelectTimeout;
static fd_set  m_fds;



int16 tftp_create(int16 sock);
void overTime(uint8 i);
void dealData(uint8 i);
void sendOACK(uint8 *recvBuff);
void sendACK_WRQ(uint8 *recvBuff);
void sendACK_DATA(uint8 i, uint8 *recvBuff);
void sendDATA(uint8 i, uint8 *recvBuff);
int16 addConn();
void closeConn(uint8 i);
void stringSpilt(uint8 *source,uint32 len,uint8 dest[][128],uint8 key);
int Pub_GetSubStr(char *substr, char *str, char ch, int sublen, uint16 *len);
void ScanCamera(uint8 *recvBuff);

#define fopen fopen2
#define fwrite fwrite2
#define fread fread2
#define fclose fclose2
#define remove remove2
#define fseek fseek2

#ifdef	NOTFILESYSTEM
	static FILE *fopen(const char *filename, const char *mode);	//文件打开函数
	static unsigned int fwrite(const void *buffer, unsigned int len, unsigned int count, FILE* index);
	static unsigned int fread(void *buffer, unsigned int len, unsigned int count, FILE* index);
	static int fclose(FILE* index);
	static int remove(const char *filename);
	static int32 fseek(FILE* index, int32 offset, int32 fromwhere);
#endif

//功能：发送一次数据
//参数：i 索引号, sendPackNo为发送的包号
//返回：从文件中读取的数据长度，0表示文件中已经没有数据
uint16 sendOneData(uint8 i, uint16 sendPackNo)
{
	uint8  buffer[2000];
	uint8  pos = 0;
	uint16  len;

	buffer[pos++] = 0;
	buffer[pos++] = 0x03;
	buffer[pos++] = (sendPackNo)/256;
	buffer[pos++] = (sendPackNo)%256;
	fseek(m_tftp[i].fd, (sendPackNo - 1) * m_blksize, NFS_SEEK_SET);
	len = fread(buffer+pos, 1, m_blksize, m_tftp[i].fd);
	sendto(m_tftp[i].socketfd, buffer, len+4, 0,
	 (struct sockaddr *)&m_tftp[i].from_addr, sizeof(m_tftp[i].from_addr));

	return len;
}

//功能：创建端口句柄
//参数：sock 端口号
//返回：成功返回创建的端口句柄,失败返回-1;
int16 tftp_create(int16 sock)
{
	struct sockaddr_in my_addr;
	int16 socketfd;
	//static int reuseFlag = 500*1024;
	unsigned int flag = 1;
	int optlen = sizeof(int);
	char optval = sizeof(char);
#ifdef WIN32
	

	WSADATA dat;
	WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32
#ifdef DM642
	int optlen = sizeof(int);
	char optval = sizeof(char);

//	fdOpenSession(TaskSelf());
#endif

	socketfd = socket(AF_INET, SOCK_DGRAM, 0);

	my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(sock);
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	setsockopt(socketfd, SOL_SOCKET, SO_BROADCAST, &optval, optlen);
    if (bind(socketfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr)) == -1)
		return -1;
//    if (setsockopt(socketfd, SOL_SOCKET, SO_SNDBUF,(const char*)&reuseFlag, sizeof reuseFlag) < 0)
//	{
//		close(socketfd);
//		return -1;
//	}
#ifdef LINUX
    flag = fcntl(socketfd,F_GETFL,0);
    fcntl(socketfd,F_SETFL,flag|O_NONBLOCK);
#endif
#ifdef WIN32
	//ioctlsocket(socketfd, FIONBIO, &flag);
#endif

	if (socketfd == -1)
		return -1;
//#ifdef WIN32
#ifdef LINUX
	///////////////////////////////////////////////zzq
    m_SelectTimeout.tv_sec = 0;
    m_SelectTimeout.tv_usec = 300;
    FD_ZERO(&m_fds);
    FD_SET(socketfd, &m_fds);
	///////////////////////////////////////////////zzq
#endif
    return socketfd; 
}


//功能：tftp初始化
//参数：无
//返回：成功 0 ，失败 -1
int32 tftp_init()
{	
	uint8 i;
	//初始化各连接的端口为-1，用此来标志该结构是否连接客户
	for(i = 0;i < MAXCONNNUM; i++)
	{
		m_tftp[i].socketfd = -1;
		m_tftp[i].fd = NULL;
		strcpy(m_tftp[i].fileName,"");
		m_tftp[i].packNo = -1;//收到的包号
		m_tftp[i].sendBufLen = 0;
		m_tftp[i].recvBufLen = 0;
		m_tftp[i].count = 0;
		m_tftp[i].stat = 0;
		m_tftp[i].from_addr.sin_family = AF_INET;
#ifdef DM642
		m_tftp[i].tv.tv_usec = 0;
#endif
	}
	//创建端口句柄
	m_tftp[0].socketfd = tftp_create(69);
	if (m_tftp[0].socketfd < 0)
		return -1;
	return 0;
}


//功能：tftp服务器
//参数：无
//返回：无
void tftp_run()
{
	uint8 i;
	dealData(0);
	for(i=1;i<MAXCONNNUM;i++)
	{
		if (m_tftp[i].socketfd >= 0)
		{
			dealData(i);
			overTime(i);
		}
	}
}



//功能：超时处理函数
//参数：i 端口结构索引
//返回：无
void overTime(uint8 i)
{
	int16 j;
	int64 n;	//
#ifndef WIN32
	struct timeval tv;	//时间结构
#else
	struct _timeb tstruct;	//Windows时间
#endif
	
#ifdef LINUX
	//取当前时间
	gettimeofday(&tv,NULL);

	//得到上次收包与当前时间差
	if (tv.tv_sec < m_tftp[i].tv.tv_sec)
		m_tftp[i].tv.tv_sec = tv.tv_sec;

	//得到上次收包与当前时间差
	n = (tv.tv_sec - m_tftp[i].tv.tv_sec);
	n *= 1000;
	n += (tv.tv_usec - m_tftp[i].tv.tv_usec)/1000;
#endif
#ifdef WIN32
	//windows平台取时间
	_ftime(&tstruct);
	
	//获取时间
	if (tstruct.time < m_tftp[i].tstruct.time)
		m_tftp[i].tstruct.time = tstruct.time;

	//得到上次收包与当前时间差
	n = (tstruct.time - m_tftp[i].tstruct.time)*1000 + \
		(tstruct.millitm - m_tftp[i].tstruct.millitm);
#endif
#ifdef DM642
	tv.tv_usec = CLK_gethtime()/CLK_countspms();

	//得到上次收包与当前时间差
	if (tv.tv_usec < m_tftp[i].tv.tv_usec)
		m_tftp[i].tv.tv_usec = tv.tv_usec;

	//得到上次收包与当前时间差
	n = tv.tv_usec - m_tftp[i].tv.tv_usec;
#endif

	//如果没超时，返回
	if (n < OVERTIME)
		return;
	//如果超时，并且重发次数不够，则再次重发，否则关闭
	if(m_tftp[i].count < RESENDTIME)
	{
		if(m_tftp[i].reSendData == 0)	//如果不是数据则按原来的进行处理
			sendto(m_tftp[i].socketfd, m_tftp[i].sendBuf, m_tftp[i].sendBufLen,	0,
			(struct sockaddr *)&m_tftp[i].from_addr, sizeof(m_tftp[i].from_addr));
		if(m_tftp[i].reSendData == 1)	//如果是数据
		{
//			if(m_tftp[i].packNo == 0)
//				m_tftp[i].packNo = 1;
			fseek(m_tftp[i].fd, (m_tftp[i].packNo-1)* m_blksize, NFS_SEEK_SET);
			for(j = 0; j < SENDWINDOW; j++)
			{
				m_tftp[i].dataAvailable = sendOneData(i, m_tftp[i].packNo + j);
				if(m_tftp[i].dataAvailable < m_blksize)	//数据发送完
					break;
			}
		}
		m_tftp[i].count++;//重发次数加1
#ifdef LINUX
	//更新收到包的时间
	gettimeofday(&m_tftp[i].tv, NULL);
#endif
#ifdef WIN32
	_ftime(&m_tftp[i].tstruct);
#endif
#ifdef DM642
	m_tftp[i].tv.tv_usec = CLK_gethtime()/CLK_countspms();
#endif
		return;
	}
	else	//如果超时，并且已重发指定次数，则关闭该端口
	{
		if(m_tftp[i].stat == 3){  //只有收到的文件才删除
			remove(m_tftp[i].fileName);
		}
		printf("-- overtime \n");
		closeConn(i);
	}
		
}	
	
	
//功能：TFTP数据包处理函数
//参数：i 端口结构索引
//返回：无
//说明:	数据包格式
//		读写请求:操作码(2Byte)|文件名(字符串N Byte)|0(1Byte)|模式(N Byte)|0(1Byte)
//		数据传输:操作码(2Byte)|块编号(2Byte)|数据(0-512Byte)
//		应答报文:操作码(2Byre)|块编号(2Byte)
//		错误报文:操作码(2Byte)|差错码(2Byte)|差错信息(N Byte)|0(1Byte)
void dealData(uint8 i)
{
	uint8 cmd;			 //命令码
	uint8 recvBuff[2048];//收到的包
	int16 recvLen = 0;	 //收到的包长度
	int32 fromlen = 0;	 //收到数据的端口结构长度

#ifdef LINUX //def WIN32
 	FD_ZERO(&m_fds);
    FD_SET(m_tftp[i].socketfd, &m_fds);

	if (select(m_tftp[i].socketfd+1, &m_fds, NULL, NULL, &m_SelectTimeout) <= 0)
    		return;
   	if (!FD_ISSET(m_tftp[i].socketfd, &m_fds))
		return;
#endif
/////////////////////////////////////////////zzq

	fromlen = sizeof(struct sockaddr_in);
	recvLen = recvfrom(m_tftp[i].socketfd, recvBuff, sizeof(recvBuff),
			 0, (struct sockaddr *)&m_tftp[i].from_addr, &fromlen);	

	//最小长度的包为应答包 长度为4 所以小于4的包都不处理�
	if (recvLen < 4)
		return;
	
	m_tftp[i].recvBufLen = recvLen;
	
	//命令码两位 但是recvBuff[0]固定为0
	cmd = recvBuff[1];

	switch(cmd)
	{
		case 1:	//RRQ-- //RRQ-- 读请求-客户向设备请求数据
			sendOACK(recvBuff);
			break;
		case 2:	//WRQ-- 写请求报文
			sendACK_WRQ(recvBuff);//
			break;
		case 3:	//DATA--数据传送报文--数据由客户传向设备
			sendACK_DATA(i,recvBuff);//
			break;
		case 4:	//ACK-- 确认报文----数据由设备传向客户
			sendDATA(i,recvBuff);
			break;
		default:
			ScanCamera(recvBuff);
			break;
	}
}

void sendOACK(uint8 *recvBuff)
{
	uint8 buffer[16];
	uint8 pos = 0;
	int16 index;
	uint8 buff[6][128];
	int16 len;
	uint8 blkSize[8];
	uint16 recvLen;
	uint16 i;
		
	index = addConn();
	if (index < 0)
		return;

#ifdef LINUX
	gettimeofday(&m_tftp[index].tv, NULL);
#endif
#ifdef WIN32
	_ftime(&m_tftp[index].tstruct);
#endif
#ifdef DM642
	m_tftp[index].tv.tv_usec = CLK_gethtime()/CLK_countspms();
#endif
	m_tftp[index].count = 0;
	m_tftp[index].reSendData = 0;
	recvLen = m_tftp[0].recvBufLen;
	//stringSpilt(recvBuff,m_tftp[0].recvBufLen,buff,0x00);

	for(i=0; i<recvLen-2; i++)
		recvBuff[i] = recvBuff[i+2];
	recvLen -= 2;
	i = 0;

	while(1)
	{
		len = Pub_GetSubStr((char*)buff[i], (char*)recvBuff, '\0', 127, &recvLen);
		if (len != 0)
			break;
		i++;
	}
	
	strcpy(m_tftp[index].fileName,(char *)buff[0]);
//	printf("filename is %s", m_tftp[index].fileName\n);
	
	for(i = 1; i < MAXCONNNUM; i ++)
	{//zzh add here to avoid two client access one file resource
		if((i != index) && (m_tftp[i].socketfd >= 0))
		{
			if(strcmp(m_tftp[i].fileName, m_tftp[index].fileName) == 0)
			{
				closeConn(index);
				return;
			}
		}
	}

	m_tftp[index].fd = fopen(m_tftp[index].fileName,"rb");
	if (m_tftp[index].fd == NULL)
	{
		return;
	}
	memset(buffer, 0, 16);
	if(strncmp(buff[2], "blksize", 7) != 0)
		m_blksize = 512;
	else
	{
		m_blksize = atoi((const char*)buff[3]);
	}
	if(m_blksize > BLKSIZE)
		m_blksize = BLKSIZE;
	if(m_blksize < 512)
		m_blksize = 512;

	buffer[0] = 0x00;
	buffer[1] = 0x06;
	buffer[2] = 'b';
	buffer[3] = 'l';
	buffer[4] = 'k';
	buffer[5] = 's';
	buffer[6] = 'i';
	buffer[7] = 'z';
	buffer[8] = 'e';
	buffer[9] = 0x00;
	pos = 10;
	sprintf((char *)blkSize, "%d", m_blksize);
	memcpy(buffer + pos, blkSize, strlen((char *)blkSize));
	pos += strlen((char *)blkSize);
	buffer[pos++] = 0;
	
	memcpy(m_tftp[index].sendBuf,(char *)buffer,pos);
	m_tftp[index].sendBufLen = pos;
	
	len = sendto(m_tftp[index].socketfd, buffer, pos, 0,
		(struct sockaddr *)&m_tftp[index].from_addr, sizeof(m_tftp[index].from_addr));
	if(len <= 0)
		;//printf("tftp error: %d\n", fdError());
	if (len > 0)
	{
		m_tftp[index].packNo = 0;
//		m_tftp[index].resPackNo = 0;
	}
#ifdef UC_MS02
	if(((int)m_tftp[index].fd==8) || ((int)m_tftp[index].fd==6))
	{
		//printf("(int)m_tftp[index].fd=%d stat =2,inex=%d\n",(int)m_tftp[index].fd,index);
		m_tftp[index].stat = 2;//wbb add
	}
#endif
}
void sendACK_WRQ(uint8 *recvBuff)
{
	int8  buffer[4];
	uint8 pos;
	int16 len = 0;
	int16 index;
	uint8 buff[6][128];
	uint16 recvLen;
	uint16 i;
	
	if ((index = addConn()) < 0)
		return;

#ifdef LINUX
	gettimeofday(&m_tftp[index].tv, NULL);
#endif
#ifdef WIN32
	_ftime(&m_tftp[index].tstruct);
#endif
#ifdef DM642
	m_tftp[index].tv.tv_usec = CLK_gethtime()/CLK_countspms();
#endif
	m_tftp[index].count = 0;
	m_tftp[index].reSendData = 0;
	recvLen = m_tftp[0].recvBufLen;
	for(i=0; i<recvLen-2; i++)
		recvBuff[i] = recvBuff[i+2];
	recvLen -= 2;
	i = 0;
	while(1)
	{
		len = Pub_GetSubStr((char*)buff[i], (char*)recvBuff, '\0', 127, &recvLen);
		if (len != 0)
			break;
		i++;
		if (i >= 6)//2006-12-06 zzq add
			break;
	}
	strcpy(m_tftp[index].fileName,(char *)buff[0]);	
	m_tftp[index].fd = fopen(m_tftp[index].fileName,"wb+");
	if (m_tftp[index].fd == NULL)
		return;	
#ifdef	NOTFILESYSTEM
	m_listFile[(int)m_tftp[index].fd]->fileLen = 0;
#endif
	pos = 0;
	buffer[pos++] = 0;
	buffer[pos++] = 0x04;
	buffer[pos++] = 0;
	buffer[pos++] = 0;
	
	memcpy(m_tftp[index].sendBuf,buffer,4);
	m_tftp[index].sendBufLen = 4;

//	ScanCamera(buffer);	
	len = sendto(m_tftp[index].socketfd, buffer, 4, 0, 
		(struct sockaddr *)&m_tftp[index].from_addr, sizeof(m_tftp[index].from_addr));
	if (len > 0)
	{
		m_tftp[index].packNo = 1;
	}
	else
		;//printf("error wrq send: %d\n", fdError());
	m_tftp[index].stat = 3;
}
void sendACK_DATA(uint8 i, uint8 *recvBuff)
{
	int8   buffer[4];
	uint8  pos = 0;
	int32  packNo = 0;
	uint32 len = 0;
	
	packNo = recvBuff[3] + recvBuff[2] * 256;
	if(m_tftp[i].packNo != packNo)
	{
		//printf("pack !=\n");
		return;
	}
	
#ifdef LINUX
	gettimeofday(&m_tftp[i].tv, NULL);
#endif
#ifdef WIN32
	_ftime(&m_tftp[i].tstruct);
#endif
#ifdef DM642
	m_tftp[i].tv.tv_usec = CLK_gethtime()/CLK_countspms();
#endif
	m_tftp[i].count = 0;
	m_tftp[i].reSendData = 0;
	
	len = fwrite(recvBuff+4, 1, m_tftp[i].recvBufLen-4, m_tftp[i].fd);
	if ( len < BLKSIZE )//2014-4-10 传输块大小不是512，　是BLKSIZE, lhy/lx改
//	if ( len < 512 )
	{	
//		printf("recv finish\n");
		buffer[pos++] = 0;
		buffer[pos++] = 0x04;
		buffer[pos++] = (int8)(packNo>>8);
		buffer[pos++] = (int8)packNo;
		
		memcpy(m_tftp[i].sendBuf,buffer,pos);
		m_tftp[i].sendBufLen = 4;
		
		len = sendto(m_tftp[i].socketfd, buffer, 4, 0, (struct sockaddr *)&m_tftp[i].from_addr, sizeof(m_tftp[i].from_addr));
		
		if (len > 0)
		{
			m_tftp[i].stat = 1;
			closeConn(i);
		}
		return;
	}
	
	if ( len != (m_tftp[i].recvBufLen - 4))
	{
//		printf("recv len != write len\n");
		return;
	}

	buffer[pos++] = 0;
	buffer[pos++] = 0x04;
	buffer[pos++] = (int8)(packNo>>8);
	buffer[pos++] = (int8)packNo;
	
	memcpy(m_tftp[i].sendBuf, buffer, pos);
	m_tftp[i].sendBufLen = 4;
	
	len = sendto(m_tftp[i].socketfd, buffer, 4, 0, 
		(struct sockaddr *)&m_tftp[i].from_addr, sizeof(m_tftp[i].from_addr));
	if (len > 0)
	{
		m_tftp[i].packNo++;
	}
}

void sendDATA(uint8 i, uint8 *recvBuff)
{
	int32  packNo;
	int16  j;

#ifdef LINUX
	gettimeofday(&m_tftp[i].tv, NULL);
#endif
#ifdef WIN32
	_ftime(&m_tftp[i].tstruct);
#endif
#ifdef DM642
	m_tftp[i].tv.tv_usec = CLK_gethtime()/CLK_countspms();
#endif
	m_tftp[i].count = 0;


	m_tftp[i].reSendData = 1;
	packNo = recvBuff[3] + recvBuff[2] * 256;
	
	if(packNo != m_tftp[i].packNo)
	{
//		printf("m_tftp[%d].packNo = %d , nowACK_PackNo = %d\n",
//				i,
//				m_tftp[i].packNo,
//				packNo);
		return;
	}

	if(packNo == 0)
	{
		m_tftp[i].packNo = 1;
		for(j = 0; j < SENDWINDOW; j++)
		{
			m_tftp[i].dataAvailable = sendOneData(i, m_tftp[i].packNo + j);
			//TSK_sleep(1);
			if(m_tftp[i].dataAvailable < m_blksize)
			{
				m_tftp[i].stat = 2;
#ifdef UC_MS02
				//wbb add 文件发送成功后，才会从服务器中删除文件
				if(m_tftp[i].fd != NULL && ((int)m_tftp[i].fd==6 || (int)m_tftp[i].fd==8))
					m_listFile[(int)m_tftp[i].fd]->fileLen = 0;
#endif
				closeConn(i);
				break;
			}
		}

	}
	else
	{
		if(m_tftp[i].dataAvailable == m_blksize)
		{
			m_tftp[i].packNo++;
			m_tftp[i].dataAvailable = sendOneData(i, m_tftp[i].packNo+SENDWINDOW-1);
		}
		else
		{
			m_tftp[i].stat = 2;
#ifdef UC_MS02
			//wbb add 文件发送成功后，才会从服务器中删除文件
			if(m_tftp[i].fd != NULL && ((int)m_tftp[i].fd==6 || (int)m_tftp[i].fd==8))
				m_listFile[(int)m_tftp[i].fd]->fileLen = 0;
#endif
			closeConn(i);
			return;
		
		}
	}
}

uint16 g_ReportPort;
extern uint8 g_Ip[4];

int16 addConn()
{
	uint8 i;
	uint16 sock = 0;
	for(i=1;i<MAXCONNNUM;i++)
	{
		if (m_tftp[i].socketfd < 0)
		{
			sock = 0;//g_Ip[3] + g_ReportPort + 255*(i-1);
//			printf("%d :sock port is %d.\n", i, sock);
			m_tftp[i].socketfd = tftp_create(sock);
			if ( m_tftp[i].socketfd < 0)
				return -1;
			m_tftp[i].from_addr.sin_addr.s_addr = m_tftp[0].from_addr.sin_addr.s_addr;
			m_tftp[i].from_addr.sin_port = m_tftp[0].from_addr.sin_port;
//			printf("num = %d\n",i);//-----------------
			break;
		}
	}
	if(i == MAXCONNNUM)
	{
		return -1;
	}
	return i;
}

void closeConn(uint8 i)
{
#ifdef WIN32
	closesocket(m_tftp[i].socketfd);
#else
	close(m_tftp[i].socketfd);
#endif
#ifdef WIN32
	///////////////////////////////////////////////zzq
    FD_CLR(m_tftp[i].socketfd, &m_fds);
	///////////////////////////////////////////////zzq
#endif
	m_tftp[i].socketfd = -1;
	fclose(m_tftp[i].fd);
#ifndef UC_MS02
	if(m_tftp[i].stat != 1)//对于设备接收到的文件，不清空;其它清空
	{
		if(m_tftp[i].fd != NULL)
			m_listFile[(int)m_tftp[i].fd]->fileLen = 0;
	}
#else  //wbb add
	//对于设备接收到的文件，不清空
	//对于设备发出的新文件,reg_pic reg_db不清空，只有发送完成后清空,修改后超时不删除文件
	if(m_tftp[i].stat != 1)
	{
		if(m_tftp[i].stat != 2)
		{
			if(m_tftp[i].fd != NULL)
				m_listFile[(int)m_tftp[i].fd]->fileLen = 0;
			//printf("m_tftp[i].stat != 1 fillne=0,fd=%d,index=%d,state=%d\n",(int)m_tftp[i].fd,i,m_tftp[i].stat);
		}else if((m_tftp[i].stat == 2) && ((int)m_tftp[i].fd!=8) && ((int)m_tftp[i].fd!=6))
		{
			if(m_tftp[i].fd != NULL)
				m_listFile[(int)m_tftp[i].fd]->fileLen = 0;
			//printf("m_tftp[i].stat != 1 fillne=0,fd=%d,index=%d state=%d\n",(int)m_tftp[i].fd,i,m_tftp[i].stat);
		}
	}
#endif

	m_tftp[i].fd = NULL;
	m_tftp[i].packNo = 0;
	m_tftp[i].sendBufLen = 0;
	m_tftp[i].recvBufLen = 0;
	m_tftp[i].count = 0;	
#ifdef WIN32
	WSACleanup();
#endif // WIN32
}

void stringSpilt(uint8 *source,uint32 len,uint8 dest[][128],uint8 key)
{
	uint32  i = 0;
	int8  recvBuff[2048];
	int8  *token=NULL;
	int8  str[1];
	
	str[0] = key;
	str[1] = 0x00;
	
	memcpy(recvBuff,source+2,len-2);
	token = strtok(recvBuff, str);
	while(token!=NULL)
	{
		strcpy((char *)dest[i],token);
		token = strtok( NULL, str );
		i++;
	}
}

int Pub_GetSubStr(char *substr, char *str, char ch, int sublen, uint16 *len)
{
	uint16 i,j,k=0;
	char buf[256]="";
	
	if (sublen > 255)
		sublen = 255;
	substr[0] = '\0';
	for(i=0;i<*len;i++)
	{
		if (str[i] == ch)
		{
			strcpy(substr, buf);
			for(j=0;j<*len-i-1;j++)
				str[j] = str[j+i+1];
			str[j] = '\0';
			*len = *len-i-1;
			if (strlen(substr) > 0)
				return 0;
			else
				return -2;
		}
		if (str[i] != 0x09 && str[i] != 0x0d && str[i] != 0x0a)
		{
			buf[k++] = str[i];
			buf[k] = '\0';
			if (i >= sublen)
				return -1;
		}
	}
	return -1;
}
void need_switch_to_video()
{
	int8 filename[12];
	uint8 i;
	
	for(i=1;i<MAXCONNNUM;i++)
	{
		if (m_tftp[i].stat == 1)
		{
			strncpy(filename, m_tftp[i].fileName, 12);
			if(strcmp(filename, "image.jpg") == 0)
				g_RunStat = 1;
		}
	}
}

//功能:	取得上次发出的文件名
//参数:	无
//返回:	成功返回指针 失败返回空
int8 * new_get_filename()
{
	uint8 i;
	
	for(i=1;i<MAXCONNNUM;i++)
	{
		if (m_tftp[i].stat == 1)
		{
			m_tftp[i].stat = 0;
			return m_tftp[i].fileName;
		}
	}
	return NULL;
}


//功能:	取得上次收到的文件名
//参数:	无
//返回:	成功返回指针 失败返回空
int8 * new_put_filename()
{
	uint8 i;
	
	for(i=1;i<MAXCONNNUM;i++)
	{
		if (m_tftp[i].stat == 2)
		{
#ifdef UC_MS02 //wbb add 防止stat赋值为0，导致超时把文件清空
			if((int)m_tftp[i].fd !=6 && (int)m_tftp[i].fd!=8)
				m_tftp[i].stat = 0;
#else
			m_tftp[i].stat = 0;
#endif
			if (strcmp(m_tftp[i].fileName,"image.jpg") == 0)
				m_listFile[4]->fileLen = 0;
			return m_tftp[i].fileName;
		}
	}
	return NULL;
}

void ScanCamera(uint8 *recvBuff)
{
#define MANUFACTORY_ID	"Maxfort_Vision-NDK350"
	
	int16 slen, idlen;
	int8 *ip = "255.255.255.255";
	int8 buffer[100];
	idlen  = strlen(MANUFACTORY_ID);
	
	if(memcmp(recvBuff, MANUFACTORY_ID, idlen) != 0)
		return;
	//printf("----scan dev 1\n");
	slen  = idlen;
	if(recvBuff[slen] == 0x01)	//��MAC��IP
	{
	//	printf("----scan dev 2\n");
		slen ++;
		strcpy(buffer, MANUFACTORY_ID);
		buffer[slen++] = g_MacAddr[0];
		buffer[slen++] = g_MacAddr[1];
		buffer[slen++] = g_MacAddr[2];
		buffer[slen++] = g_MacAddr[3];
		buffer[slen++] = g_MacAddr[4];
		buffer[slen++] = g_MacAddr[5];

		memcpy(buffer+slen, g_Ip, 4);
		slen += 4;							//zzh add mask
		memcpy(buffer+slen, g_Mask, 4);
		slen += 4;							//zzh add gateway
		memcpy(buffer+slen, g_GateWay, 4);
		slen += 4;
		m_tftp[0].from_addr.sin_addr.s_addr = inet_addr(ip);
		sendto(m_tftp[0].socketfd, buffer, slen, 0, \
		      (struct sockaddr *)&m_tftp[0].from_addr, \
		      sizeof(m_tftp[0].from_addr));
		return;//	slen = idlen	// ���������recvBuff[slen] == 0x02 �п��ܻ��b
	}

	/*if(recvBuff[slen] == 0x02)	//дMAC��IP
	{
		if((recvBuff[slen+1] != g_MacAddr[0]) || (recvBuff[slen+2]) != g_MacAddr[1] \
		|| (recvBuff[slen+3] != g_MacAddr[2]) || (recvBuff[slen+4] != g_MacAddr[3]) \
		|| (recvBuff[slen+5] != g_MacAddr[4]) || (recvBuff[slen+6] != g_MacAddr[5]))
			return;
		
		slen += 7;
		memcpy(g_Ip, &recvBuff[slen], 4);
		slen += 4;							//zzh add mask
		memcpy(g_Mask, &recvBuff[slen], 4);
		slen += 4;							//zzh add gateway
		memcpy(g_GateWay, &recvBuff[slen], 4);
	}*/
}

#ifdef	NOTFILESYSTEM

int16 tftp_addFile(TftpFile *tftpfile)
{
	m_listNum += 1;
	if(m_listNum > MAXLISTFILE)
	{
		m_listNum -= 1;
		return -1;
	}
	
	m_listFile[m_listNum] = tftpfile;

	return 0;

}

//功能:	打开和指定名称相对应的缓冲区
//参数:
//		filename:和缓冲区相关联的名字
//		mode:打开模式 目前不支持
//返回:	0:失败 >0:成功
static FILE *fopen(const char *filename, const char *mode)
{
	int i;

	for(i = 1; i <= m_listNum; i++)
	{
		if(m_listNum == MAXLISTFILE)
		{
			return (FILE*)0;
		}
		if(memcmp(m_listFile[i]->Filename, filename, strlen(filename)) == 0)
		{
			m_listFile[i]->fileCurrent = 0;
			return (FILE*)i;
		}
	}
	return (FILE*)0;
}

//功能:	向指定的缓冲区写入数据
//参数:
//		buffer:数据所在的缓冲区
//		len无用
//		count:要写的长度
//		index:缓冲区的索引
//返回:	0:失败 >0写入的数据长度
static unsigned int fwrite(const void *buffer, unsigned int len, unsigned int count, FILE* index)
{
	if(index == 0)
        return 0;
	m_listFile[(int)index]->fileLen += count;
	if(m_listFile[(int)index]->fileLen > m_listFile[(int)index]->fileMaxlen)
		return 0;
	memcpy(m_listFile[(int)index]->lpFile + m_listFile[(int)index]->fileCurrent, buffer, count);
	m_listFile[(int)index]->fileCurrent = m_listFile[(int)index]->fileLen;
	
	return count;
}

//功能:	读取缓冲区中的数据
//参数:
//		buffer:存放读取数据的缓冲区
//		len:无用
//		count:要读取的长度
//		index:数据存放缓冲区的索引
//返回:	0:失败 >0:读取的长度
static unsigned int fread(void *buffer, unsigned int len, unsigned int count, FILE* index)
{
	 if(index == 0)  
        return 0;
	if(m_listFile[(int)index]->fileCurrent >= m_listFile[(int)index]->fileLen)
		return 0;

	if((m_listFile[(int)index]->fileLen - m_listFile[(int)index]->fileCurrent) < m_blksize)
		count = m_listFile[(int)index]->fileLen - m_listFile[(int)index]->fileCurrent;

	memcpy(buffer, m_listFile[(int)index]->lpFile + m_listFile[(int)index]->fileCurrent, count);
	m_listFile[(int)index]->fileCurrent += count;

	return count;
}

//功能:	关闭对应的缓冲区
//参数:
//		index:缓冲区的索引
//返回:	1:成功
static int fclose(FILE* index)
{
	if (index == 0)
		return 0;
	m_listFile[(int)index]->fileCurrent = 0;
	//lxremark 2014-3-13 接收文件长度在fopen中删除m_listFile[(int)index]->fileLen = 0;
	return 0;
}

//功能:	删除文件,就是将相应缓冲区中的数据清楚
//参数:
//		filename:要删除的文件名
//返回:	1:成功 0:失败
static int remove(const char *filename)
{
	uint8 i;
   
	for(i = 1; i <= m_listNum; i++)
	{
		if(m_listNum == MAXLISTFILE)
		{
			return 0;
		}
		if(memcmp(m_listFile[i]->Filename, filename, strlen(filename)) == 0)
			m_listFile[i]->fileLen = 0;
	}

	return 0;

}


//功能：文件指针移动函数
//参数：index 索引号 offset 偏移地址 fromwhere 开始位置
//返回：偏移地址
//处理逻辑：移动fileCurrent，要判断是否超过文件长度，只支持从文件头开始移动
static int32 fseek(FILE* index, int32 offset, int32 fromwhere)
{   
	if(index == 0)  
        return 0;
	if(offset >= m_listFile[(int)index]->fileLen)
		return 0;
	m_listFile[(int)index]->fileCurrent = offset;
	return offset;
}

#endif
